/*
	提供服务初始化，包括数据库，Redis，Mq，日志文件等
*/
package initialize

import (
	"fmt"
	"github.com/go-redis/redis/v7"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
	"github.com/sbabiv/rmqconn"
	"github.com/spf13/viper"
	"os"
	"runtime"
	"strings"
	"time"
)

var (
	MsqlDb          *gorm.DB             //数据库客户端
	Config          *viper.Viper         //全局配置
	RedisClient     *redis.Client        //redis单机客户端
	MqClient        rmqconn.Connecter    //全局Mq客户端-商城vs直播
)

//	提供系统初始化，全局变量
func Init(config *viper.Viper) {
	Config = config
	var err error
	//mysql配置
	MsqlDb, err = gorm.Open("mysql", config.GetString("Mysql.user")+":"+config.GetString("Mysql.password")+"@tcp("+config.GetString("Mysql.host")+":"+config.GetString("Mysql.Port")+")/"+config.GetString("Mysql.database")+"?charset=utf8mb4&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}
	MsqlDb.DB().SetMaxIdleConns(10)
	MsqlDb.DB().SetMaxOpenConns(100)
	MsqlDb.DB().SetConnMaxLifetime(10 * time.Minute)
	// 激活链接
	if err = MsqlDb.DB().Ping(); err != nil {
		panic(err)
	}

	//	Redis客户端
	RedisClient = redis.NewClient(&redis.Options{
		Addr:     config.GetString("Redis.default.addr"),
		Password: config.GetString("Redis.default.password"), // no password set
		DB:       config.GetInt("Redis.default.db"),  // use default DB
	})
	err = RedisClient.Ping().Err()
	if err != nil {
		panic(err)
	}

	//	RMQ客户端
	MqClient, err = rmqconn.Open("amqp://"+config.GetString("RabbitMQ.UserName")+":"+config.GetString("RabbitMQ.PassWord")+"@"+config.GetString("RabbitMQ.Host")+":"+config.GetString("RabbitMQ.Port"), rmqconn.Dial)
	if err != nil {
		panic(err)
	}


}

//	查找调用包名，文件名，函数名 方便日志查找
func findCaller(skip int) string {
	file := ""
	line := 0
	var pc uintptr
	// 遍历调用栈的最大索引为第11层.
	for i := 0; i < 11; i++ {
		file, line, pc = getCaller(skip + i)
		// 过滤掉所有logrus包，即可得到生成代码信息
		if !strings.HasPrefix(file, "golog") {
			break
		}
	}

	fullFnName := runtime.FuncForPC(pc)

	fnName := ""
	if fullFnName != nil {
		fnNameStr := fullFnName.Name()
		// 取得函数名
		parts := strings.Split(fnNameStr, ".")
		fnName = parts[len(parts)-1]
	}

	return fmt.Sprintf("%s:%d:%s()", file, line, fnName)
}

//	查找调用包名，文件名，函数名 方便日志查找
func getCaller(skip int) (string, int, uintptr) {
	pc, file, line, ok := runtime.Caller(skip)
	if !ok {
		return "", 0, pc
	}
	n := 0

	// 获取包名
	for i := len(file) - 1; i > 0; i-- {
		if file[i] == '/' {
			n++
			if n >= 2 {
				file = file[i+1:]
				break
			}
		}
	}
	return file, line, pc
}


//	创建日志文件目录和文件
func newLogFile() *os.File {
	path := "./logs/"
	_, err := os.Stat(path)
	if os.IsNotExist(err) {
		err := os.MkdirAll(path, os.ModePerm)
		if err != nil {
			panic("创建日志logs文件失败")
		}
	}
	filename := path + time.Now().Format("20060102") + ".log"
	// Open the file, this will append to the today's file if server restarted.
	file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		panic(err)
	}
	return file
}